use std::io::{self, BufRead, BufReader, Write};
use std::process::{Child, ChildStderr, ChildStdin, ChildStdout, Command, Stdio};
use std::sync::{Arc, Mutex};
use std::thread;

/// 平台类型枚举
#[derive(Debug, Clone, Copy)]
pub enum Platform {
    Windows,
    Unix,
}

/// Shell管理器，负责启动和管理shell进程
pub struct ShellManager {
    child: Option<Child>,
    stdin: Option<ChildStdin>,
    stdout: Option<ChildStdout>,
    stderr: Option<ChildStderr>,
    platform: Platform,
    is_running: bool,

    // 使用Arc<Mutex>来在线程间共享输出
    output_buffer: Arc<Mutex<String>>,
    command_history: Arc<Mutex<Vec<String>>>,
}

impl ShellManager {
    /// 创建新的Shell管理器
    pub fn new() -> Self {
        let platform = if cfg!(target_os = "windows") {
            Platform::Windows
        } else {
            Platform::Unix
        };

        Self {
            child: None,
            stdin: None,
            stdout: None,
            stderr: None,
            platform,
            is_running: false,
            output_buffer: Arc::new(Mutex::new(String::new())),
            command_history: Arc::new(Mutex::new(Vec::new())),
        }
    }

    /// 启动shell进程
    pub fn start(&mut self) -> io::Result<()> {
        if self.is_running {
            return Ok(());
        }

        // 根据平台选择shell
        let (shell, args): (&str, Vec<&str>) = match self.platform {
            Platform::Windows => ("cmd.exe", vec!["/K"]), // 保持cmd运行
            Platform::Unix => ("/usr/bin/bash", vec!["-i"]), // 使用交互模式
        };

        let mut child = Command::new(shell)
            .args(args)
            .stdin(Stdio::piped())
            .stdout(Stdio::piped())
            .stderr(Stdio::piped())
            .spawn()?;

        // 保存管道句柄
        self.stdin = child.stdin.take();
        self.stdout = child.stdout.take();
        self.stderr = child.stderr.take();
        self.child = Some(child);
        self.is_running = true;

        // 启动输出读取线程
        self.start_output_reader();

        // 检查进程是否真的在运行
        if let Some(child) = &mut self.child {
            if let Ok(Some(_)) = child.try_wait() {
                self.is_running = false;
            }
        }

        Ok(())
    }

    /// 停止shell进程
    pub fn stop(&mut self) -> io::Result<()> {
        if let Some(mut child) = self.child.take() {
            child.kill()?;
            child.wait()?;
            self.is_running = false;
        }
        Ok(())
    }

    /// 发送命令到shell
    pub fn send_command(&mut self, command: &str) -> io::Result<()> {
        if !self.is_running {
            return Err(io::Error::new(
                io::ErrorKind::NotConnected,
                "Shell is not running",
            ));
        }

        if let Some(stdin) = &mut self.stdin {
            // 添加命令到历史
            {
                let mut history = self.command_history.lock().unwrap();
                history.push(command.to_string());
            }

            // 发送命令到shell，添加换行
            let command_with_newline = format!("{}\n", command);
            stdin.write_all(command_with_newline.as_bytes())?;
            stdin.flush()?;
            Ok(())
        } else {
            Err(io::Error::new(
                io::ErrorKind::BrokenPipe,
                "Stdin is not available",
            ))
        }
    }

    /// 获取输出内容
    pub fn get_output(&self) -> String {
        let buffer = self.output_buffer.lock().unwrap();
        buffer.clone()
    }

    /// 清空输出缓冲区
    pub fn clear_output(&mut self) {
        let mut buffer = self.output_buffer.lock().unwrap();
        buffer.clear();
    }

    /// 获取命令历史
    pub fn get_command_history(&self) -> Vec<String> {
        let history = self.command_history.lock().unwrap();
        history.clone()
    }

    /// 检查shell是否在运行
    pub fn is_running(&self) -> bool {
        self.is_running
    }

    /// 启动输出读取线程
    fn start_output_reader(&mut self) {
        let stdout = match self.stdout.take() {
            Some(stdout) => stdout,
            None => return,
        };

        let stderr = match self.stderr.take() {
            Some(stderr) => stderr,
            None => return,
        };

        let output_buffer_stdout = Arc::clone(&self.output_buffer);
        let output_buffer_stderr = Arc::clone(&self.output_buffer);

        // 启动stdout读取线程 - 使用阻塞读取
        thread::spawn(move || {
            let reader = BufReader::new(stdout);
            for line in reader.lines() {
                match line {
                    Ok(line) => {
                        let mut output = output_buffer_stdout.lock().unwrap();
                        output.push_str(&line);
                        output.push('\n');
                    }
                    Err(_) => break,
                }
            }
        });

        // 启动stderr读取线程 - 使用阻塞读取
        thread::spawn(move || {
            let reader = BufReader::new(stderr);
            for line in reader.lines() {
                match line {
                    Ok(line) => {
                        let mut output = output_buffer_stderr.lock().unwrap();
                        output.push_str(&line);
                        output.push('\n');
                    }
                    Err(_) => break,
                }
            }
        });
    }
}

impl Default for ShellManager {
    fn default() -> Self {
        Self::new()
    }
}

impl Drop for ShellManager {
    fn drop(&mut self) {
        let _ = self.stop();
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_platform_detection() {
        let manager = ShellManager::new();
        if cfg!(target_os = "windows") {
            assert!(matches!(manager.platform, Platform::Windows));
        } else {
            assert!(matches!(manager.platform, Platform::Unix));
        }
    }

    #[test]
    fn test_shell_creation() {
        let mut manager = ShellManager::new();
        assert!(!manager.is_running());

        let result = manager.start();
        // 在某些环境下可能无法启动shell，所以不强制要求成功
        if result.is_ok() {
            assert!(manager.is_running());

            // 清理
            let _ = manager.stop();
        }
    }
}
